extern ThreadError gThreadError; // set by thread routines
extern Boolean gSystemLocked;
typedef long ThreadType;
#define StackCopy 0
//const ThreadType HeapStack = ; // unimplemented
typedef long ThreadState;
#define running 0 // the Thread is the active context
#define pending 1 // the Thread is awaiting scheduleing (ie. on gPendingQueue)
#define blocked 2 // the Thread is on a semaphore
#define sleeping 3 // the Thread is not blocked or pending
#define ended 4 // the Thread is about to be free'd
struct Thread {
struct Thing fThing;
ThreadType fType;
ThreadState fState;
Boolean fLocked; // if the ThreadHandle and fStack are Locked - avoids copious calls to HLock/Hunlock
Handle fStack; // the storage for the stack data - if ThreadType == HeapStack this is HLock'ed
ThreadProc fCopyContext; // copy current context - store in fStack
ThreadProc fSwapIn; // called to context switch "this" thread in
ThreadProc fSwapOut; // calls fSchedule then fSwapIn on the nextThread
ThreadProc fFree; // called to dispose of the Thread
ScheduleProc fSchedule; // queue this thread (if necessary), return the next one
long fUserBytes[8]; // for user use
};
typedef struct Thread Thread;
// manager routines:
pascal void InitThreads(ThreadHandle mainThread, Boolean usesFPU); // if the "mainThread" requires special methods, create it - don't start it and pass it in
pascal ThreadHandle GetCurrentThread();
pascal void Yield();
pascal void ExitThreads(); // while gPendingQueue is not empty Yield
// thread routines:
#define kDefaultStackSize 1024
pascal ThreadHandle NewThread(long stackSize /* ThreadType t */);
pascal void StartThread(ThreadHandle theThread); // call fCopy proc and Wake
pascal Boolean InThread(ThreadHandle theThread); // true if theThread is running
pascal void Sleep(ThreadHandle theThread); // remove form gPendingQueue (or swap out if running) place on gSleepingQueue
pascal void Wake(ThreadHandle theThread); // place on gPendingQueue
pascal void EndThread(ThreadHandle theThread); // call fFree - never returns, end of context
pascal ThreadHandle Spawn(ThreadHandle, pascal void (*threadProc)(ThreadHandle, long), long stackSize, long refcon);
// convienence routine:
pascal Boolean InNewThread(ThreadHandle* theThread, long stackSize); // NewThread, StartThread, InThread
// default methods:
pascal void TCopyContext(ThreadHandle); // copy the current context
pascal void TSwapIn(ThreadHandle); // make this thread's context the active context
pascal void TSwapOut(ThreadHandle); // save the current context (or free the thread if fState == ended)
pascal void TFree(ThreadHandle); // dispose of the thread
pascal ThreadHandle TSchedule(ThreadHandle); // returns the next thread to be run, queue this thread is necessary